#ifndef Algebra_Matrix_h
#define Algebra_Matrix_h

#include "AlgebraModule.h"
#include <vector>

SG_NAMESPACE_OPEN

namespace Algebra
{
    /// @brief 稠密矩阵
    ///
    /// 元素采用 Row-majored 排列
    class ALGEBRA_EXPORT Matrix
    {
    public:
        Matrix () = default;
        Matrix (std::size_t rowSize, std::size_t colSize, Real_t value = 0.0);

        /** @brief 通过 vector 构造 Matrix
         *
         *  @param [in] rowSize 行数
         *  @param [in] colSize 列数
         *  @param [in] elements 矩阵元素
         *  @param [in] value 指定填充值
         *  @author     Du WeiXing 2024,03.17修改
         *  通过`elements`构造`Matrix`，当`elements`元素不足时，用指定的`value`填充。
         */
        Matrix (std::size_t rowSize, std::size_t colSize, const std::vector<Real_t>& elements, Real_t value = 0.0);

        /// @brief 对 [] 重载
        Real_t* operator[] (std::size_t row);

        /// @brief 对 += 重载
        Matrix& operator+= (const Matrix& b);

        /// @brief 对 -= 重载
        Matrix& operator-= (const Matrix& b);

        /** @brief 矩阵减法
         *  @author Yuan Chenxi 2024,05.10添加
         */
        Matrix operator- (const Matrix& b) const;

        /** @brief 矩阵加法
         *  @author Yuan Chenxi 2024,05.10添加
         */
        Matrix operator+ (const Matrix& b) const;

        /// @brief 矩阵乘以数
        Matrix operator* (const Real_t factor) const;

        /// @brief 矩阵乘法
        Matrix operator* (const Matrix& b) const;

        /// @brief 转置
        Matrix Transpose () const;

        /// @brief 逆矩阵
        Matrix Inverse () const;

        /** @brief 子块提取
         * 
         *  从当前矩阵第 i 行第 j 列取出 m 行 n 列子块矩阵，起始索引 i、j 从 0 开始
         */
        Matrix Block (std::size_t i, std::size_t j, std::size_t m, std::size_t n);

        /** @brief 块填充
         *
         *  将当前矩阵的第 rows(i) 行第 cols(j) 列的值修改成 b(i,j)
         */
        Matrix& BlockFill (const std::vector<std::size_t>& rows, const std::vector<std::size_t>& cols, const Matrix& b);

        /** @brief 块填充 2, 将 b 整块填充到当前矩阵中
         *
         *  将当前矩阵的第 rows(rowStart + i) 行第 cols(colStart + j) 列的值修改成 b(i,j)
         */
        Matrix& BlockFill (std::size_t rowStart, std::size_t colStart, const Matrix& b);

        /** @brief 块累加
         *
         *  将当前矩阵的第 rows(i) 行第 cols(j) 列的值修改成 b(i,j)
         */
        Matrix& BlockSum (const std::vector<std::size_t>& rows, const std::vector<std::size_t>& cols, const Matrix& sub);

        /// @brief 括号运算符，访问矩阵元素
        /// @param row 行索引
        /// @param col 列索引
        /// @return 元素值
        const Real_t& operator() (const std::size_t row, const std::size_t col) const;

        /// @brief 括号运算符访问矩阵元素，非常量版本
        /// 提供对元素值修改
        Real_t& operator() (const std::size_t row, const std::size_t col);

        std::size_t GetRowSize () const
        {
            return m_rowSize;
        }
        std::size_t GetColSize () const
        {
            return m_colSize;
        }

    private:
        std::size_t                                  m_rowSize;
        std::size_t                                  m_colSize;
        std::vector<Real_t>                          m_elements;
    };

    inline Real_t* Matrix::operator[] (std::size_t row)
    {
        return &m_elements[row * m_colSize];
    }

    inline const Real_t& Matrix::operator() (const std::size_t row, const std::size_t col) const
    {
        return m_elements[row * m_colSize + col];
    }

    inline Real_t& Matrix::operator() (const std::size_t row, const std::size_t col)
    {
        return m_elements[row * m_colSize + col];
    }

    /// @brief alias of Matrix
    using Matrixd = Matrix;

    /// @brief 快速计算 2*2 矩阵的逆矩阵
    ALGEBRA_EXPORT Matrix inverse2X2 (const Matrix& m);

    /// @brief 快速计算 3*3 矩阵的逆矩阵
    ALGEBRA_EXPORT Matrix inverse3X3 (const Matrix& m, Real_t& det);

    /// @brief 快速计算 2*2 矩阵的行列式
    ALGEBRA_EXPORT Real_t det2X2 (const Matrix& m);

    /// @brief 快速计算 3*3 矩阵的行列式
    ALGEBRA_EXPORT Real_t det3X3 (const Matrix& m);

    /// @brief 快速计算 4*4 矩阵的行列式
    ALGEBRA_EXPORT Real_t det4X4 (const Matrix& m);

    /// @brief 生成单位矩阵
    /// @param size 单位矩阵矩阵维度
    ALGEBRA_EXPORT Matrix identity (const std::size_t size);

    /// @brief 生成向量的反对称矩阵
    ALGEBRA_EXPORT Matrix skew (Real_t x, Real_t y, Real_t z);

        /// @brief 水平合并两个矩阵产生一个新的矩阵
    ALGEBRA_EXPORT Matrix hstack (const Matrix& m, const Matrix& n);

    /// @brief 垂直合并两个矩阵产生一个新的矩阵
    ALGEBRA_EXPORT Matrix vstack (const Matrix& m, const Matrix& n);

    /// @brief 去除矩阵某个行列索引产生一个新的矩阵,axis = 0 表示行，axis = 1 表示列
    ALGEBRA_EXPORT Matrix remove (const Matrix& m, const std::size_t Index, const std::size_t axis);

    /**
     * @brief    三维空间非标准正交基标准正交化
     *           也可用于数据 ZCA（Zero-phase Component Analysis）白化（Whitening）
     * @param    basis 三维空间非标准正交基，按列组成矩阵
     * @return   标准正交基，按列组成矩阵
     * @author   Du Weixing
     * @date     2025.04.28
     */
    ALGEBRA_EXPORT Matrix orthonormalize (const Matrix& basis);


    /// @brief  矩阵是否相等
    ALGEBRA_EXPORT bool operator== (const Matrix& matrixA, const Matrix& matrixB);

    //@}
}

SG_NAMESPACE_CLOSE

#endif // Algebra_Matrix_h
